package jmine.tec.rpc.server.representation.representers.reflection;

import java.beans.PropertyDescriptor;
import java.util.Map;

import jmine.tec.rpc.server.representation.RepresentationContext;

import org.apache.commons.beanutils.PropertyUtils;

/**
 * Representador de propriedades que são mapas.
 * 
 * @author lundberg
 * @param <R> tipo de representação
 * @param <E> tipo de entidade representada
 */
public class MapPropertyRepresenter<R, E> implements PropertyRepresenter<R, E> {

    /**
     * {@inheritDoc}
     */
    public boolean isApplicableTo(PropertyDescriptor representationProperty) {
        return RepresenterUtil.classesMatch(Map.class, representationProperty);
    }

    /**
     * {@inheritDoc}
     */
    public void representProperty(RepresentationContext context, R representation, PropertyDescriptor representationProperty, E object)
            throws Exception {
        Class<?> keyType = RepresenterUtil.getParameterizedPropertyType(representationProperty, 0, representation.getClass());
        Class<?> valueType = RepresenterUtil.getParameterizedPropertyType(representationProperty, 1, representation.getClass());
        Map<?, ?> map = (Map) PropertyUtils.getProperty(object, representationProperty.getName());
        Map<?, ?> mapRepresentation = this.createRepresentation(context, keyType, valueType, map);
        PropertyUtils.setProperty(representation, representationProperty.getName(), mapRepresentation);
    }

    /**
     * Cria uma representação do mapa
     * 
     * @param context context
     * @param keyType keyType
     * @param valueType valueType
     * @param map map
     * @return Map
     */
    protected Map<?, ?> createRepresentation(RepresentationContext context, Class<?> keyType, Class<?> valueType, Map<?, ?> map) {
        return context.representObjects(keyType, valueType, map);
    }
}
